//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2024 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif
@_spi(SotoInternal) import SotoCore

extension Detective {
    // MARK: Enums

    public enum DatasourcePackage: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case asffSecurityhubFinding = "ASFF_SECURITYHUB_FINDING"
        case detectiveCore = "DETECTIVE_CORE"
        case eksAudit = "EKS_AUDIT"
        public var description: String { return self.rawValue }
    }

    public enum DatasourcePackageIngestState: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case disabled = "DISABLED"
        case started = "STARTED"
        case stopped = "STOPPED"
        public var description: String { return self.rawValue }
    }

    public enum EntityType: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case iamRole = "IAM_ROLE"
        case iamUser = "IAM_USER"
        public var description: String { return self.rawValue }
    }

    public enum ErrorCode: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case internalError = "INTERNAL_ERROR"
        case invalidGraphArn = "INVALID_GRAPH_ARN"
        case invalidRequestBody = "INVALID_REQUEST_BODY"
        public var description: String { return self.rawValue }
    }

    public enum Field: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case createdTime = "CREATED_TIME"
        case severity = "SEVERITY"
        case status = "STATUS"
        public var description: String { return self.rawValue }
    }

    public enum IndicatorType: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case flaggedIpAddress = "FLAGGED_IP_ADDRESS"
        case impossibleTravel = "IMPOSSIBLE_TRAVEL"
        case newAso = "NEW_ASO"
        case newGeolocation = "NEW_GEOLOCATION"
        case newUserAgent = "NEW_USER_AGENT"
        case relatedFinding = "RELATED_FINDING"
        case relatedFindingGroup = "RELATED_FINDING_GROUP"
        case ttpObserved = "TTP_OBSERVED"
        public var description: String { return self.rawValue }
    }

    public enum InvitationType: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case invitation = "INVITATION"
        case organization = "ORGANIZATION"
        public var description: String { return self.rawValue }
    }

    public enum MemberDisabledReason: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case volumeTooHigh = "VOLUME_TOO_HIGH"
        case volumeUnknown = "VOLUME_UNKNOWN"
        public var description: String { return self.rawValue }
    }

    public enum MemberStatus: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case acceptedButDisabled = "ACCEPTED_BUT_DISABLED"
        case enabled = "ENABLED"
        case invited = "INVITED"
        case verificationFailed = "VERIFICATION_FAILED"
        case verificationInProgress = "VERIFICATION_IN_PROGRESS"
        public var description: String { return self.rawValue }
    }

    public enum Reason: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case awsThreatIntelligence = "AWS_THREAT_INTELLIGENCE"
        public var description: String { return self.rawValue }
    }

    public enum Severity: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case critical = "CRITICAL"
        case high = "HIGH"
        case informational = "INFORMATIONAL"
        case low = "LOW"
        case medium = "MEDIUM"
        public var description: String { return self.rawValue }
    }

    public enum SortOrder: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case asc = "ASC"
        case desc = "DESC"
        public var description: String { return self.rawValue }
    }

    public enum State: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case active = "ACTIVE"
        case archived = "ARCHIVED"
        public var description: String { return self.rawValue }
    }

    public enum Status: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case failed = "FAILED"
        case running = "RUNNING"
        case successful = "SUCCESSFUL"
        public var description: String { return self.rawValue }
    }

    // MARK: Shapes

    public struct AcceptInvitationRequest: AWSEncodableShape {
        /// The ARN of the behavior graph that the member account is accepting the invitation for. The member account status in the behavior graph must be INVITED.
        public let graphArn: String

        @inlinable
        public init(graphArn: String) {
            self.graphArn = graphArn
        }

        public func validate(name: String) throws {
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
        }

        private enum CodingKeys: String, CodingKey {
            case graphArn = "GraphArn"
        }
    }

    public struct AccessDeniedException: AWSErrorShape {
        /// The SDK default error code associated with the access denied exception.
        public let errorCode: ErrorCode?
        /// The SDK default explanation of why access was denied.
        public let errorCodeReason: String?
        public let message: String?
        /// The error code associated with the access denied exception.
        public let subErrorCode: ErrorCode?
        ///  An explanation of why access was denied.
        public let subErrorCodeReason: String?

        @inlinable
        public init(errorCode: ErrorCode? = nil, errorCodeReason: String? = nil, message: String? = nil, subErrorCode: ErrorCode? = nil, subErrorCodeReason: String? = nil) {
            self.errorCode = errorCode
            self.errorCodeReason = errorCodeReason
            self.message = message
            self.subErrorCode = subErrorCode
            self.subErrorCodeReason = subErrorCodeReason
        }

        private enum CodingKeys: String, CodingKey {
            case errorCode = "ErrorCode"
            case errorCodeReason = "ErrorCodeReason"
            case message = "Message"
            case subErrorCode = "SubErrorCode"
            case subErrorCodeReason = "SubErrorCodeReason"
        }
    }

    public struct Account: AWSEncodableShape {
        /// The account identifier of the Amazon Web Services account.
        public let accountId: String
        /// The Amazon Web Services account root user email address for the Amazon Web Services account.
        public let emailAddress: String

        @inlinable
        public init(accountId: String, emailAddress: String) {
            self.accountId = accountId
            self.emailAddress = emailAddress
        }

        public func validate(name: String) throws {
            try self.validate(self.accountId, name: "accountId", parent: name, max: 12)
            try self.validate(self.accountId, name: "accountId", parent: name, min: 12)
            try self.validate(self.accountId, name: "accountId", parent: name, pattern: "^[0-9]+$")
            try self.validate(self.emailAddress, name: "emailAddress", parent: name, max: 64)
            try self.validate(self.emailAddress, name: "emailAddress", parent: name, min: 1)
            try self.validate(self.emailAddress, name: "emailAddress", parent: name, pattern: "^.+@(?:(?:(?!-)[A-Za-z0-9-]{1,62})?[A-Za-z0-9]{1}\\.)+[A-Za-z]{2,63}$")
        }

        private enum CodingKeys: String, CodingKey {
            case accountId = "AccountId"
            case emailAddress = "EmailAddress"
        }
    }

    public struct Administrator: AWSDecodableShape {
        /// The Amazon Web Services account identifier of the Detective administrator account for the organization.
        public let accountId: String?
        /// The date and time when the Detective administrator account was enabled. The value is an ISO8601 formatted string. For example, 2021-08-18T16:35:56.284Z.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var delegationTime: Date?
        /// The ARN of the organization behavior graph.
        public let graphArn: String?

        @inlinable
        public init(accountId: String? = nil, delegationTime: Date? = nil, graphArn: String? = nil) {
            self.accountId = accountId
            self.delegationTime = delegationTime
            self.graphArn = graphArn
        }

        private enum CodingKeys: String, CodingKey {
            case accountId = "AccountId"
            case delegationTime = "DelegationTime"
            case graphArn = "GraphArn"
        }
    }

    public struct BatchGetGraphMemberDatasourcesRequest: AWSEncodableShape {
        /// The list of Amazon Web Services accounts to get data source package information on.
        public let accountIds: [String]
        /// The ARN of the behavior graph.
        public let graphArn: String

        @inlinable
        public init(accountIds: [String], graphArn: String) {
            self.accountIds = accountIds
            self.graphArn = graphArn
        }

        public func validate(name: String) throws {
            try self.accountIds.forEach {
                try validate($0, name: "accountIds[]", parent: name, max: 12)
                try validate($0, name: "accountIds[]", parent: name, min: 12)
                try validate($0, name: "accountIds[]", parent: name, pattern: "^[0-9]+$")
            }
            try self.validate(self.accountIds, name: "accountIds", parent: name, max: 200)
            try self.validate(self.accountIds, name: "accountIds", parent: name, min: 1)
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
        }

        private enum CodingKeys: String, CodingKey {
            case accountIds = "AccountIds"
            case graphArn = "GraphArn"
        }
    }

    public struct BatchGetGraphMemberDatasourcesResponse: AWSDecodableShape {
        /// Details on the status of data source packages for members of the behavior graph.
        public let memberDatasources: [MembershipDatasources]?
        /// Accounts that data source package information could not be retrieved for.
        public let unprocessedAccounts: [UnprocessedAccount]?

        @inlinable
        public init(memberDatasources: [MembershipDatasources]? = nil, unprocessedAccounts: [UnprocessedAccount]? = nil) {
            self.memberDatasources = memberDatasources
            self.unprocessedAccounts = unprocessedAccounts
        }

        private enum CodingKeys: String, CodingKey {
            case memberDatasources = "MemberDatasources"
            case unprocessedAccounts = "UnprocessedAccounts"
        }
    }

    public struct BatchGetMembershipDatasourcesRequest: AWSEncodableShape {
        /// The ARN of the behavior graph.
        public let graphArns: [String]

        @inlinable
        public init(graphArns: [String]) {
            self.graphArns = graphArns
        }

        public func validate(name: String) throws {
            try self.graphArns.forEach {
                try validate($0, name: "graphArns[]", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
            }
            try self.validate(self.graphArns, name: "graphArns", parent: name, max: 50)
            try self.validate(self.graphArns, name: "graphArns", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case graphArns = "GraphArns"
        }
    }

    public struct BatchGetMembershipDatasourcesResponse: AWSDecodableShape {
        /// Details on the data source package history for an member of the behavior graph.
        public let membershipDatasources: [MembershipDatasources]?
        /// Graphs that data source package information could not be retrieved for.
        public let unprocessedGraphs: [UnprocessedGraph]?

        @inlinable
        public init(membershipDatasources: [MembershipDatasources]? = nil, unprocessedGraphs: [UnprocessedGraph]? = nil) {
            self.membershipDatasources = membershipDatasources
            self.unprocessedGraphs = unprocessedGraphs
        }

        private enum CodingKeys: String, CodingKey {
            case membershipDatasources = "MembershipDatasources"
            case unprocessedGraphs = "UnprocessedGraphs"
        }
    }

    public struct CreateGraphRequest: AWSEncodableShape {
        /// The tags to assign to the new behavior graph. You can add up to 50 tags. For each tag, you provide the tag key and the tag value. Each tag key can contain up to 128 characters. Each tag value can contain up to 256 characters.
        public let tags: [String: String]?

        @inlinable
        public init(tags: [String: String]? = nil) {
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.key, name: "tags.key", parent: name, pattern: "^(?!aws:)[a-zA-Z+-=._:/]+$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
            try self.validate(self.tags, name: "tags", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "Tags"
        }
    }

    public struct CreateGraphResponse: AWSDecodableShape {
        /// The ARN of the new behavior graph.
        public let graphArn: String?

        @inlinable
        public init(graphArn: String? = nil) {
            self.graphArn = graphArn
        }

        private enum CodingKeys: String, CodingKey {
            case graphArn = "GraphArn"
        }
    }

    public struct CreateMembersRequest: AWSEncodableShape {
        /// The list of Amazon Web Services accounts to invite or to enable. You can invite or enable up to 50 accounts at a time. For each invited account, the account list contains the account identifier and the Amazon Web Services account root user email address. For organization accounts in the organization behavior graph, the email address is not required.
        public let accounts: [Account]
        /// if set to true, then the invited accounts do not receive email notifications. By default, this is set to false, and the invited accounts receive email notifications. Organization accounts in the organization behavior graph do not receive email notifications.
        public let disableEmailNotification: Bool?
        /// The ARN of the behavior graph.
        public let graphArn: String
        /// Customized message text to include in the invitation email message to the invited member accounts.
        public let message: String?

        @inlinable
        public init(accounts: [Account], disableEmailNotification: Bool? = nil, graphArn: String, message: String? = nil) {
            self.accounts = accounts
            self.disableEmailNotification = disableEmailNotification
            self.graphArn = graphArn
            self.message = message
        }

        public func validate(name: String) throws {
            try self.accounts.forEach {
                try $0.validate(name: "\(name).accounts[]")
            }
            try self.validate(self.accounts, name: "accounts", parent: name, max: 50)
            try self.validate(self.accounts, name: "accounts", parent: name, min: 1)
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
            try self.validate(self.message, name: "message", parent: name, max: 1000)
            try self.validate(self.message, name: "message", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case accounts = "Accounts"
            case disableEmailNotification = "DisableEmailNotification"
            case graphArn = "GraphArn"
            case message = "Message"
        }
    }

    public struct CreateMembersResponse: AWSDecodableShape {
        /// The set of member account invitation or enablement requests that Detective was able to process. This includes accounts that are being verified, that failed verification, and that passed verification and are being sent an invitation or are being enabled.
        public let members: [MemberDetail]?
        /// The list of accounts for which Detective was unable to process the invitation or enablement request. For each account, the list provides the reason why the request could not be processed. The list includes accounts that are already member accounts in the behavior graph.
        public let unprocessedAccounts: [UnprocessedAccount]?

        @inlinable
        public init(members: [MemberDetail]? = nil, unprocessedAccounts: [UnprocessedAccount]? = nil) {
            self.members = members
            self.unprocessedAccounts = unprocessedAccounts
        }

        private enum CodingKeys: String, CodingKey {
            case members = "Members"
            case unprocessedAccounts = "UnprocessedAccounts"
        }
    }

    public struct DatasourcePackageIngestDetail: AWSDecodableShape {
        /// Details on which data source packages are ingested for a member account.
        public let datasourcePackageIngestState: DatasourcePackageIngestState?
        /// The date a data source package was enabled for this account
        public let lastIngestStateChange: [DatasourcePackageIngestState: TimestampForCollection]?

        @inlinable
        public init(datasourcePackageIngestState: DatasourcePackageIngestState? = nil, lastIngestStateChange: [DatasourcePackageIngestState: TimestampForCollection]? = nil) {
            self.datasourcePackageIngestState = datasourcePackageIngestState
            self.lastIngestStateChange = lastIngestStateChange
        }

        private enum CodingKeys: String, CodingKey {
            case datasourcePackageIngestState = "DatasourcePackageIngestState"
            case lastIngestStateChange = "LastIngestStateChange"
        }
    }

    public struct DatasourcePackageUsageInfo: AWSDecodableShape {
        /// Total volume of data in bytes per day ingested for a given data source package.
        public let volumeUsageInBytes: Int64?
        /// The data and time when the member account data volume was last updated. The value is an ISO8601 formatted string. For example, 2021-08-18T16:35:56.284Z.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var volumeUsageUpdateTime: Date?

        @inlinable
        public init(volumeUsageInBytes: Int64? = nil, volumeUsageUpdateTime: Date? = nil) {
            self.volumeUsageInBytes = volumeUsageInBytes
            self.volumeUsageUpdateTime = volumeUsageUpdateTime
        }

        private enum CodingKeys: String, CodingKey {
            case volumeUsageInBytes = "VolumeUsageInBytes"
            case volumeUsageUpdateTime = "VolumeUsageUpdateTime"
        }
    }

    public struct DateFilter: AWSEncodableShape {
        /// A timestamp representing the end date of the time period until when data is filtered, including the end date.
        @CustomCoding<ISO8601DateCoder>
        public var endInclusive: Date
        /// A timestamp representing the start of the time period from when data is filtered, including the start date.
        @CustomCoding<ISO8601DateCoder>
        public var startInclusive: Date

        @inlinable
        public init(endInclusive: Date, startInclusive: Date) {
            self.endInclusive = endInclusive
            self.startInclusive = startInclusive
        }

        private enum CodingKeys: String, CodingKey {
            case endInclusive = "EndInclusive"
            case startInclusive = "StartInclusive"
        }
    }

    public struct DeleteGraphRequest: AWSEncodableShape {
        /// The ARN of the behavior graph to disable.
        public let graphArn: String

        @inlinable
        public init(graphArn: String) {
            self.graphArn = graphArn
        }

        public func validate(name: String) throws {
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
        }

        private enum CodingKeys: String, CodingKey {
            case graphArn = "GraphArn"
        }
    }

    public struct DeleteMembersRequest: AWSEncodableShape {
        /// The list of Amazon Web Services account identifiers for the member accounts to remove from the behavior graph. You can remove up to 50 member accounts at a time.
        public let accountIds: [String]
        /// The ARN of the behavior graph to remove members from.
        public let graphArn: String

        @inlinable
        public init(accountIds: [String], graphArn: String) {
            self.accountIds = accountIds
            self.graphArn = graphArn
        }

        public func validate(name: String) throws {
            try self.accountIds.forEach {
                try validate($0, name: "accountIds[]", parent: name, max: 12)
                try validate($0, name: "accountIds[]", parent: name, min: 12)
                try validate($0, name: "accountIds[]", parent: name, pattern: "^[0-9]+$")
            }
            try self.validate(self.accountIds, name: "accountIds", parent: name, max: 50)
            try self.validate(self.accountIds, name: "accountIds", parent: name, min: 1)
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
        }

        private enum CodingKeys: String, CodingKey {
            case accountIds = "AccountIds"
            case graphArn = "GraphArn"
        }
    }

    public struct DeleteMembersResponse: AWSDecodableShape {
        /// The list of Amazon Web Services account identifiers for the member accounts that Detective successfully removed from the behavior graph.
        public let accountIds: [String]?
        /// The list of member accounts that Detective was not able to remove from the behavior graph. For each member account, provides the reason that the deletion could not be processed.
        public let unprocessedAccounts: [UnprocessedAccount]?

        @inlinable
        public init(accountIds: [String]? = nil, unprocessedAccounts: [UnprocessedAccount]? = nil) {
            self.accountIds = accountIds
            self.unprocessedAccounts = unprocessedAccounts
        }

        private enum CodingKeys: String, CodingKey {
            case accountIds = "AccountIds"
            case unprocessedAccounts = "UnprocessedAccounts"
        }
    }

    public struct DescribeOrganizationConfigurationRequest: AWSEncodableShape {
        /// The ARN of the organization behavior graph.
        public let graphArn: String

        @inlinable
        public init(graphArn: String) {
            self.graphArn = graphArn
        }

        public func validate(name: String) throws {
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
        }

        private enum CodingKeys: String, CodingKey {
            case graphArn = "GraphArn"
        }
    }

    public struct DescribeOrganizationConfigurationResponse: AWSDecodableShape {
        /// Indicates whether to automatically enable new organization accounts as member accounts in the organization behavior graph.
        public let autoEnable: Bool?

        @inlinable
        public init(autoEnable: Bool? = nil) {
            self.autoEnable = autoEnable
        }

        private enum CodingKeys: String, CodingKey {
            case autoEnable = "AutoEnable"
        }
    }

    public struct DisassociateMembershipRequest: AWSEncodableShape {
        /// The ARN of the behavior graph to remove the member account from. The member account's member status in the behavior graph must be ENABLED.
        public let graphArn: String

        @inlinable
        public init(graphArn: String) {
            self.graphArn = graphArn
        }

        public func validate(name: String) throws {
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
        }

        private enum CodingKeys: String, CodingKey {
            case graphArn = "GraphArn"
        }
    }

    public struct EnableOrganizationAdminAccountRequest: AWSEncodableShape {
        /// The Amazon Web Services account identifier of the account to designate as the Detective administrator account for the organization.
        public let accountId: String

        @inlinable
        public init(accountId: String) {
            self.accountId = accountId
        }

        public func validate(name: String) throws {
            try self.validate(self.accountId, name: "accountId", parent: name, max: 12)
            try self.validate(self.accountId, name: "accountId", parent: name, min: 12)
            try self.validate(self.accountId, name: "accountId", parent: name, pattern: "^[0-9]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case accountId = "AccountId"
        }
    }

    public struct FilterCriteria: AWSEncodableShape {
        /// Filter the investigation results based on when the investigation was created.
        public let createdTime: DateFilter?
        /// Filter the investigation results based on the Amazon Resource Name (ARN) of the entity.
        public let entityArn: StringFilter?
        /// Filter the investigation results based on the severity.
        public let severity: StringFilter?
        /// Filter the investigation results based on the state.
        public let state: StringFilter?
        /// Filter the investigation results based on the status.
        public let status: StringFilter?

        @inlinable
        public init(createdTime: DateFilter? = nil, entityArn: StringFilter? = nil, severity: StringFilter? = nil, state: StringFilter? = nil, status: StringFilter? = nil) {
            self.createdTime = createdTime
            self.entityArn = entityArn
            self.severity = severity
            self.state = state
            self.status = status
        }

        public func validate(name: String) throws {
            try self.entityArn?.validate(name: "\(name).entityArn")
            try self.severity?.validate(name: "\(name).severity")
            try self.state?.validate(name: "\(name).state")
            try self.status?.validate(name: "\(name).status")
        }

        private enum CodingKeys: String, CodingKey {
            case createdTime = "CreatedTime"
            case entityArn = "EntityArn"
            case severity = "Severity"
            case state = "State"
            case status = "Status"
        }
    }

    public struct FlaggedIpAddressDetail: AWSDecodableShape {
        /// IP address of the suspicious entity.
        public let ipAddress: String?
        /// Details the reason the IP address was flagged as suspicious.
        public let reason: Reason?

        @inlinable
        public init(ipAddress: String? = nil, reason: Reason? = nil) {
            self.ipAddress = ipAddress
            self.reason = reason
        }

        private enum CodingKeys: String, CodingKey {
            case ipAddress = "IpAddress"
            case reason = "Reason"
        }
    }

    public struct GetInvestigationRequest: AWSEncodableShape {
        /// The Amazon Resource Name (ARN) of the behavior graph.
        public let graphArn: String
        /// The investigation ID of the investigation report.
        public let investigationId: String

        @inlinable
        public init(graphArn: String, investigationId: String) {
            self.graphArn = graphArn
            self.investigationId = investigationId
        }

        public func validate(name: String) throws {
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
            try self.validate(self.investigationId, name: "investigationId", parent: name, max: 21)
            try self.validate(self.investigationId, name: "investigationId", parent: name, min: 21)
            try self.validate(self.investigationId, name: "investigationId", parent: name, pattern: "^[0-9]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case graphArn = "GraphArn"
            case investigationId = "InvestigationId"
        }
    }

    public struct GetInvestigationResponse: AWSDecodableShape {
        /// The creation time of the investigation report in UTC time stamp format.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var createdTime: Date?
        /// The unique Amazon Resource Name (ARN). Detective supports IAM user ARNs and IAM role ARNs.
        public let entityArn: String?
        /// Type of entity. For example, Amazon Web Services accounts, such as an IAM user and/or IAM role.
        public let entityType: EntityType?
        /// The Amazon Resource Name (ARN) of the behavior graph.
        public let graphArn: String?
        /// The investigation ID of the investigation report.
        public let investigationId: String?
        /// The data and time when the investigation began. The value is an UTC ISO8601 formatted string. For example, 2021-08-18T16:35:56.284Z.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var scopeEndTime: Date?
        /// The start date and time used to set the scope time within which you want to generate the investigation report. The value is an UTC ISO8601 formatted string. For example, 2021-08-18T16:35:56.284Z.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var scopeStartTime: Date?
        /// The severity assigned is based on the likelihood and impact of the indicators of compromise discovered in the investigation.
        public let severity: Severity?
        /// The current state of the investigation. An archived investigation indicates that you have completed reviewing the investigation.
        public let state: State?
        /// The status based on the completion status of the investigation.
        public let status: Status?

        @inlinable
        public init(createdTime: Date? = nil, entityArn: String? = nil, entityType: EntityType? = nil, graphArn: String? = nil, investigationId: String? = nil, scopeEndTime: Date? = nil, scopeStartTime: Date? = nil, severity: Severity? = nil, state: State? = nil, status: Status? = nil) {
            self.createdTime = createdTime
            self.entityArn = entityArn
            self.entityType = entityType
            self.graphArn = graphArn
            self.investigationId = investigationId
            self.scopeEndTime = scopeEndTime
            self.scopeStartTime = scopeStartTime
            self.severity = severity
            self.state = state
            self.status = status
        }

        private enum CodingKeys: String, CodingKey {
            case createdTime = "CreatedTime"
            case entityArn = "EntityArn"
            case entityType = "EntityType"
            case graphArn = "GraphArn"
            case investigationId = "InvestigationId"
            case scopeEndTime = "ScopeEndTime"
            case scopeStartTime = "ScopeStartTime"
            case severity = "Severity"
            case state = "State"
            case status = "Status"
        }
    }

    public struct GetMembersRequest: AWSEncodableShape {
        /// The list of Amazon Web Services account identifiers for the member account for which to return member details. You can request details for up to 50 member accounts at a time. You cannot use GetMembers to retrieve information about member accounts that were removed from the behavior graph.
        public let accountIds: [String]
        /// The ARN of the behavior graph for which to request the member details.
        public let graphArn: String

        @inlinable
        public init(accountIds: [String], graphArn: String) {
            self.accountIds = accountIds
            self.graphArn = graphArn
        }

        public func validate(name: String) throws {
            try self.accountIds.forEach {
                try validate($0, name: "accountIds[]", parent: name, max: 12)
                try validate($0, name: "accountIds[]", parent: name, min: 12)
                try validate($0, name: "accountIds[]", parent: name, pattern: "^[0-9]+$")
            }
            try self.validate(self.accountIds, name: "accountIds", parent: name, max: 50)
            try self.validate(self.accountIds, name: "accountIds", parent: name, min: 1)
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
        }

        private enum CodingKeys: String, CodingKey {
            case accountIds = "AccountIds"
            case graphArn = "GraphArn"
        }
    }

    public struct GetMembersResponse: AWSDecodableShape {
        /// The member account details that Detective is returning in response to the request.
        public let memberDetails: [MemberDetail]?
        /// The requested member accounts for which Detective was unable to return member details. For each account, provides the reason why the request could not be processed.
        public let unprocessedAccounts: [UnprocessedAccount]?

        @inlinable
        public init(memberDetails: [MemberDetail]? = nil, unprocessedAccounts: [UnprocessedAccount]? = nil) {
            self.memberDetails = memberDetails
            self.unprocessedAccounts = unprocessedAccounts
        }

        private enum CodingKeys: String, CodingKey {
            case memberDetails = "MemberDetails"
            case unprocessedAccounts = "UnprocessedAccounts"
        }
    }

    public struct Graph: AWSDecodableShape {
        /// The ARN of the behavior graph.
        public let arn: String?
        /// The date and time that the behavior graph was created. The value is an ISO8601 formatted string. For example, 2021-08-18T16:35:56.284Z.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var createdTime: Date?

        @inlinable
        public init(arn: String? = nil, createdTime: Date? = nil) {
            self.arn = arn
            self.createdTime = createdTime
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "Arn"
            case createdTime = "CreatedTime"
        }
    }

    public struct ImpossibleTravelDetail: AWSDecodableShape {
        /// IP address where the resource was last used in the impossible travel.
        public let endingIpAddress: String?
        /// Location where the resource was last used in the impossible travel.
        public let endingLocation: String?
        /// Returns the time difference between the first and last timestamp the resource was used.
        public let hourlyTimeDelta: Int?
        /// IP address where the resource was first used in the impossible travel.
        public let startingIpAddress: String?
        /// Location where the resource was first used in the impossible travel.
        public let startingLocation: String?

        @inlinable
        public init(endingIpAddress: String? = nil, endingLocation: String? = nil, hourlyTimeDelta: Int? = nil, startingIpAddress: String? = nil, startingLocation: String? = nil) {
            self.endingIpAddress = endingIpAddress
            self.endingLocation = endingLocation
            self.hourlyTimeDelta = hourlyTimeDelta
            self.startingIpAddress = startingIpAddress
            self.startingLocation = startingLocation
        }

        private enum CodingKeys: String, CodingKey {
            case endingIpAddress = "EndingIpAddress"
            case endingLocation = "EndingLocation"
            case hourlyTimeDelta = "HourlyTimeDelta"
            case startingIpAddress = "StartingIpAddress"
            case startingLocation = "StartingLocation"
        }
    }

    public struct Indicator: AWSDecodableShape {
        /// Details about the indicators of compromise that are used to determine if a resource is involved in a security incident. An indicator of compromise (IOC) is an artifact observed in or on a network, system, or environment that can (with a high level of confidence) identify malicious activity or a security incident.
        public let indicatorDetail: IndicatorDetail?
        /// The type of indicator.
        public let indicatorType: IndicatorType?

        @inlinable
        public init(indicatorDetail: IndicatorDetail? = nil, indicatorType: IndicatorType? = nil) {
            self.indicatorDetail = indicatorDetail
            self.indicatorType = indicatorType
        }

        private enum CodingKeys: String, CodingKey {
            case indicatorDetail = "IndicatorDetail"
            case indicatorType = "IndicatorType"
        }
    }

    public struct IndicatorDetail: AWSDecodableShape {
        /// Suspicious IP addresses that are flagged, which indicates critical or severe threats based on threat intelligence by Detective. This indicator is derived from Amazon Web Services threat intelligence.
        public let flaggedIpAddressDetail: FlaggedIpAddressDetail?
        /// Identifies unusual and impossible user activity for an account.
        public let impossibleTravelDetail: ImpossibleTravelDetail?
        /// Contains details about the new Autonomous System Organization (ASO).
        public let newAsoDetail: NewAsoDetail?
        /// Contains details about the new geographic location.
        public let newGeolocationDetail: NewGeolocationDetail?
        /// Contains details about the new user agent.
        public let newUserAgentDetail: NewUserAgentDetail?
        /// Contains details about related findings.
        public let relatedFindingDetail: RelatedFindingDetail?
        /// Contains details about related finding groups.
        public let relatedFindingGroupDetail: RelatedFindingGroupDetail?
        /// Details about the indicator of compromise.
        public let ttPsObservedDetail: TTPsObservedDetail?

        @inlinable
        public init(flaggedIpAddressDetail: FlaggedIpAddressDetail? = nil, impossibleTravelDetail: ImpossibleTravelDetail? = nil, newAsoDetail: NewAsoDetail? = nil, newGeolocationDetail: NewGeolocationDetail? = nil, newUserAgentDetail: NewUserAgentDetail? = nil, relatedFindingDetail: RelatedFindingDetail? = nil, relatedFindingGroupDetail: RelatedFindingGroupDetail? = nil, ttPsObservedDetail: TTPsObservedDetail? = nil) {
            self.flaggedIpAddressDetail = flaggedIpAddressDetail
            self.impossibleTravelDetail = impossibleTravelDetail
            self.newAsoDetail = newAsoDetail
            self.newGeolocationDetail = newGeolocationDetail
            self.newUserAgentDetail = newUserAgentDetail
            self.relatedFindingDetail = relatedFindingDetail
            self.relatedFindingGroupDetail = relatedFindingGroupDetail
            self.ttPsObservedDetail = ttPsObservedDetail
        }

        private enum CodingKeys: String, CodingKey {
            case flaggedIpAddressDetail = "FlaggedIpAddressDetail"
            case impossibleTravelDetail = "ImpossibleTravelDetail"
            case newAsoDetail = "NewAsoDetail"
            case newGeolocationDetail = "NewGeolocationDetail"
            case newUserAgentDetail = "NewUserAgentDetail"
            case relatedFindingDetail = "RelatedFindingDetail"
            case relatedFindingGroupDetail = "RelatedFindingGroupDetail"
            case ttPsObservedDetail = "TTPsObservedDetail"
        }
    }

    public struct InvestigationDetail: AWSDecodableShape {
        /// The time stamp of the creation time of the investigation report. The value is an UTC ISO8601 formatted string. For example, 2021-08-18T16:35:56.284Z.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var createdTime: Date?
        /// The unique Amazon Resource Name (ARN) of the IAM user and IAM role.
        public let entityArn: String?
        /// Type of entity. For example, Amazon Web Services accounts, such as IAM user and role.
        public let entityType: EntityType?
        /// The investigation ID of the investigation report.
        public let investigationId: String?
        /// Severity based on the likelihood and impact of the indicators of compromise discovered in the investigation.
        public let severity: Severity?
        /// The current state of the investigation. An archived investigation indicates you have completed reviewing the investigation.
        public let state: State?
        /// Status based on the completion status of the investigation.
        public let status: Status?

        @inlinable
        public init(createdTime: Date? = nil, entityArn: String? = nil, entityType: EntityType? = nil, investigationId: String? = nil, severity: Severity? = nil, state: State? = nil, status: Status? = nil) {
            self.createdTime = createdTime
            self.entityArn = entityArn
            self.entityType = entityType
            self.investigationId = investigationId
            self.severity = severity
            self.state = state
            self.status = status
        }

        private enum CodingKeys: String, CodingKey {
            case createdTime = "CreatedTime"
            case entityArn = "EntityArn"
            case entityType = "EntityType"
            case investigationId = "InvestigationId"
            case severity = "Severity"
            case state = "State"
            case status = "Status"
        }
    }

    public struct ListDatasourcePackagesRequest: AWSEncodableShape {
        /// The ARN of the behavior graph.
        public let graphArn: String
        /// The maximum number of results to return.
        public let maxResults: Int?
        /// For requests to get the next page of results, the pagination token that was returned with the previous set of results. The initial request does not include a pagination token.
        public let nextToken: String?

        @inlinable
        public init(graphArn: String, maxResults: Int? = nil, nextToken: String? = nil) {
            self.graphArn = graphArn
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 200)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
            try self.validate(self.nextToken, name: "nextToken", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case graphArn = "GraphArn"
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
        }
    }

    public struct ListDatasourcePackagesResponse: AWSDecodableShape {
        /// Details on the data source packages active in the behavior graph.
        public let datasourcePackages: [DatasourcePackage: DatasourcePackageIngestDetail]?
        /// For requests to get the next page of results, the pagination token that was returned with the previous set of results. The initial request does not include a pagination token.
        public let nextToken: String?

        @inlinable
        public init(datasourcePackages: [DatasourcePackage: DatasourcePackageIngestDetail]? = nil, nextToken: String? = nil) {
            self.datasourcePackages = datasourcePackages
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case datasourcePackages = "DatasourcePackages"
            case nextToken = "NextToken"
        }
    }

    public struct ListGraphsRequest: AWSEncodableShape {
        /// The maximum number of graphs to return at a time. The total must be less than the overall limit on the number of results to return, which is currently 200.
        public let maxResults: Int?
        /// For requests to get the next page of results, the pagination token that was returned with the previous set of results. The initial request does not include a pagination token.
        public let nextToken: String?

        @inlinable
        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 200)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
            try self.validate(self.nextToken, name: "nextToken", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
        }
    }

    public struct ListGraphsResponse: AWSDecodableShape {
        /// A list of behavior graphs that the account is an administrator account for.
        public let graphList: [Graph]?
        /// If there are more behavior graphs remaining in the results, then this is the pagination token to use to request the next page of behavior graphs.
        public let nextToken: String?

        @inlinable
        public init(graphList: [Graph]? = nil, nextToken: String? = nil) {
            self.graphList = graphList
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case graphList = "GraphList"
            case nextToken = "NextToken"
        }
    }

    public struct ListIndicatorsRequest: AWSEncodableShape {
        /// The Amazon Resource Name (ARN) of the behavior graph.
        public let graphArn: String
        /// For the list of indicators of compromise that are generated by Detective investigations, see Detective investigations.
        public let indicatorType: IndicatorType?
        /// The investigation ID of the investigation report.
        public let investigationId: String
        /// Lists the maximum number of indicators in a page.
        public let maxResults: Int?
        /// Lists if there are more results available. The value of nextToken is a unique pagination token for each page. Repeat the call using the returned token to retrieve the next page. Keep all other arguments unchanged. Each pagination token expires after 24 hours. Using an expired pagination token will return a Validation Exception error.
        public let nextToken: String?

        @inlinable
        public init(graphArn: String, indicatorType: IndicatorType? = nil, investigationId: String, maxResults: Int? = nil, nextToken: String? = nil) {
            self.graphArn = graphArn
            self.indicatorType = indicatorType
            self.investigationId = investigationId
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
            try self.validate(self.investigationId, name: "investigationId", parent: name, max: 21)
            try self.validate(self.investigationId, name: "investigationId", parent: name, min: 21)
            try self.validate(self.investigationId, name: "investigationId", parent: name, pattern: "^[0-9]+$")
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 2048)
            try self.validate(self.nextToken, name: "nextToken", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case graphArn = "GraphArn"
            case indicatorType = "IndicatorType"
            case investigationId = "InvestigationId"
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
        }
    }

    public struct ListIndicatorsResponse: AWSDecodableShape {
        /// The Amazon Resource Name (ARN) of the behavior graph.
        public let graphArn: String?
        /// Lists the indicators of compromise.
        public let indicators: [Indicator]?
        /// The investigation ID of the investigation report.
        public let investigationId: String?
        /// Lists if there are more results available. The value of nextToken is a unique pagination token for each page. Repeat the call using the returned token to retrieve the next page. Keep all other arguments unchanged. Each pagination token expires after 24 hours. Using an expired pagination token will return a Validation Exception error.
        public let nextToken: String?

        @inlinable
        public init(graphArn: String? = nil, indicators: [Indicator]? = nil, investigationId: String? = nil, nextToken: String? = nil) {
            self.graphArn = graphArn
            self.indicators = indicators
            self.investigationId = investigationId
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case graphArn = "GraphArn"
            case indicators = "Indicators"
            case investigationId = "InvestigationId"
            case nextToken = "NextToken"
        }
    }

    public struct ListInvestigationsRequest: AWSEncodableShape {
        /// Filters the investigation results based on a criteria.
        public let filterCriteria: FilterCriteria?
        /// The Amazon Resource Name (ARN) of the behavior graph.
        public let graphArn: String
        /// Lists the maximum number of investigations in a page.
        public let maxResults: Int?
        /// Lists if there are more results available. The value of nextToken is a unique pagination token for each page. Repeat the call using the returned token to retrieve the next page. Keep all other arguments unchanged. Each pagination token expires after 24 hours. Using an expired pagination token will return a Validation Exception error.
        public let nextToken: String?
        /// Sorts the investigation results based on a criteria.
        public let sortCriteria: SortCriteria?

        @inlinable
        public init(filterCriteria: FilterCriteria? = nil, graphArn: String, maxResults: Int? = nil, nextToken: String? = nil, sortCriteria: SortCriteria? = nil) {
            self.filterCriteria = filterCriteria
            self.graphArn = graphArn
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.sortCriteria = sortCriteria
        }

        public func validate(name: String) throws {
            try self.filterCriteria?.validate(name: "\(name).filterCriteria")
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 100)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 2048)
            try self.validate(self.nextToken, name: "nextToken", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case filterCriteria = "FilterCriteria"
            case graphArn = "GraphArn"
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
            case sortCriteria = "SortCriteria"
        }
    }

    public struct ListInvestigationsResponse: AWSDecodableShape {
        /// Lists the summary of uncommon behavior or malicious activity which indicates a compromise.
        public let investigationDetails: [InvestigationDetail]?
        /// Lists if there are more results available. The value of nextToken is a unique pagination token for each page. Repeat the call using the returned token to retrieve the next page. Keep all other arguments unchanged. Each pagination token expires after 24 hours.
        public let nextToken: String?

        @inlinable
        public init(investigationDetails: [InvestigationDetail]? = nil, nextToken: String? = nil) {
            self.investigationDetails = investigationDetails
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case investigationDetails = "InvestigationDetails"
            case nextToken = "NextToken"
        }
    }

    public struct ListInvitationsRequest: AWSEncodableShape {
        /// The maximum number of behavior graph invitations to return in the response. The total must be less than the overall limit on the number of results to return, which is currently 200.
        public let maxResults: Int?
        /// For requests to retrieve the next page of results, the pagination token that was returned with the previous page of results. The initial request does not include a pagination token.
        public let nextToken: String?

        @inlinable
        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 200)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
            try self.validate(self.nextToken, name: "nextToken", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
        }
    }

    public struct ListInvitationsResponse: AWSDecodableShape {
        /// The list of behavior graphs for which the member account has open or accepted invitations.
        public let invitations: [MemberDetail]?
        /// If there are more behavior graphs remaining in the results, then this is the pagination token to use to request the next page of behavior graphs.
        public let nextToken: String?

        @inlinable
        public init(invitations: [MemberDetail]? = nil, nextToken: String? = nil) {
            self.invitations = invitations
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case invitations = "Invitations"
            case nextToken = "NextToken"
        }
    }

    public struct ListMembersRequest: AWSEncodableShape {
        /// The ARN of the behavior graph for which to retrieve the list of member accounts.
        public let graphArn: String
        /// The maximum number of member accounts to include in the response. The total must be less than the overall limit on the number of results to return, which is currently 200.
        public let maxResults: Int?
        /// For requests to retrieve the next page of member account results, the pagination token that was returned with the previous page of results. The initial request does not include a pagination token.
        public let nextToken: String?

        @inlinable
        public init(graphArn: String, maxResults: Int? = nil, nextToken: String? = nil) {
            self.graphArn = graphArn
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 200)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
            try self.validate(self.nextToken, name: "nextToken", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case graphArn = "GraphArn"
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
        }
    }

    public struct ListMembersResponse: AWSDecodableShape {
        /// The list of member accounts in the behavior graph. For invited accounts, the results include member accounts that did not pass verification and member accounts that have not yet accepted the invitation to the behavior graph. The results do not include member accounts that were removed from the behavior graph. For the organization behavior graph, the results do not include organization accounts that the Detective administrator account has not enabled as member accounts.
        public let memberDetails: [MemberDetail]?
        /// If there are more member accounts remaining in the results, then use this pagination token to request the next page of member accounts.
        public let nextToken: String?

        @inlinable
        public init(memberDetails: [MemberDetail]? = nil, nextToken: String? = nil) {
            self.memberDetails = memberDetails
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case memberDetails = "MemberDetails"
            case nextToken = "NextToken"
        }
    }

    public struct ListOrganizationAdminAccountsRequest: AWSEncodableShape {
        /// The maximum number of results to return.
        public let maxResults: Int?
        /// For requests to get the next page of results, the pagination token that was returned with the previous set of results. The initial request does not include a pagination token.
        public let nextToken: String?

        @inlinable
        public init(maxResults: Int? = nil, nextToken: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 200)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
            try self.validate(self.nextToken, name: "nextToken", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case maxResults = "MaxResults"
            case nextToken = "NextToken"
        }
    }

    public struct ListOrganizationAdminAccountsResponse: AWSDecodableShape {
        /// The list of Detective administrator accounts.
        public let administrators: [Administrator]?
        /// If there are more accounts remaining in the results, then this is the pagination token to use to request the next page of accounts.
        public let nextToken: String?

        @inlinable
        public init(administrators: [Administrator]? = nil, nextToken: String? = nil) {
            self.administrators = administrators
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case administrators = "Administrators"
            case nextToken = "NextToken"
        }
    }

    public struct ListTagsForResourceRequest: AWSEncodableShape {
        /// The ARN of the behavior graph for which to retrieve the tag values.
        public let resourceArn: String

        @inlinable
        public init(resourceArn: String) {
            self.resourceArn = resourceArn
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "ResourceArn")
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListTagsForResourceResponse: AWSDecodableShape {
        /// The tag values that are assigned to the behavior graph. The request returns up to 50 tag values.
        public let tags: [String: String]?

        @inlinable
        public init(tags: [String: String]? = nil) {
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "Tags"
        }
    }

    public struct MemberDetail: AWSDecodableShape {
        /// The Amazon Web Services account identifier for the member account.
        public let accountId: String?
        /// The Amazon Web Services account identifier of the administrator account for the behavior graph.
        public let administratorId: String?
        /// The state of a data source package for the behavior graph.
        public let datasourcePackageIngestStates: [DatasourcePackage: DatasourcePackageIngestState]?
        /// For member accounts with a status of ACCEPTED_BUT_DISABLED, the reason that the member account is not enabled. The reason can have one of the following values:    VOLUME_TOO_HIGH - Indicates that adding the member account would cause the data volume for the behavior graph to be too high.    VOLUME_UNKNOWN - Indicates that Detective is unable to verify the data volume for the member account. This is usually because the member account is not enrolled in Amazon GuardDuty.
        public let disabledReason: MemberDisabledReason?
        /// The Amazon Web Services account root user email address for the member account.
        public let emailAddress: String?
        /// The ARN of the behavior graph.
        public let graphArn: String?
        /// The type of behavior graph membership. For an organization account in the organization behavior graph, the type is ORGANIZATION. For an account that was invited to a behavior graph, the type is INVITATION.
        public let invitationType: InvitationType?
        /// For invited accounts, the date and time that Detective sent the invitation to the account. The value is an ISO8601 formatted string. For example, 2021-08-18T16:35:56.284Z.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var invitedTime: Date?
        /// The Amazon Web Services account identifier of the administrator account for the behavior graph.
        public let masterId: String?
        /// The member account data volume as a percentage of the maximum allowed data volume. 0 indicates 0 percent, and 100 indicates 100 percent. Note that this is not the percentage of the behavior graph data volume. For example, the data volume for the behavior graph is 80 GB per day. The maximum data volume is 160 GB per day. If the data volume for the member account is 40 GB per day, then PercentOfGraphUtilization is 25. It represents 25% of the maximum allowed data volume.
        public let percentOfGraphUtilization: Double?
        /// The date and time when the graph utilization percentage was last updated. The value is an ISO8601 formatted string. For example, 2021-08-18T16:35:56.284Z.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var percentOfGraphUtilizationUpdatedTime: Date?
        /// The current membership status of the member account. The status can have one of the following values:    INVITED - For invited accounts only. Indicates that the member was sent an invitation but has not yet responded.    VERIFICATION_IN_PROGRESS - For invited accounts only, indicates that Detective is verifying that the account identifier and email address provided for the member account match. If they do match, then Detective sends the invitation. If the email address and account identifier don't match, then the member cannot be added to the behavior graph. For organization accounts in the organization behavior graph, indicates that Detective is verifying that the account belongs to the organization.    VERIFICATION_FAILED - For invited accounts only. Indicates that the account and email address provided for the member account do not match, and Detective did not send an invitation to the account.    ENABLED - Indicates that the member account currently contributes data to the behavior graph. For invited accounts, the member account accepted the invitation. For organization accounts in the organization behavior graph, the Detective administrator account enabled the organization account as a member account.    ACCEPTED_BUT_DISABLED - The account accepted the invitation, or was enabled by the Detective administrator account, but is prevented from contributing data to the behavior graph. DisabledReason provides the reason why the member account is not enabled.   Invited accounts that declined an invitation or that were removed from the behavior graph are not included. In the organization behavior graph, organization accounts that the Detective administrator account did not enable are not included.
        public let status: MemberStatus?
        /// The date and time that the member account was last updated. The value is an ISO8601 formatted string. For example, 2021-08-18T16:35:56.284Z.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var updatedTime: Date?
        /// Details on the volume of usage for each data source package in a behavior graph.
        public let volumeUsageByDatasourcePackage: [DatasourcePackage: DatasourcePackageUsageInfo]?
        /// The data volume in bytes per day for the member account.
        public let volumeUsageInBytes: Int64?
        /// The data and time when the member account data volume was last updated. The value is an ISO8601 formatted string. For example, 2021-08-18T16:35:56.284Z.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var volumeUsageUpdatedTime: Date?

        @inlinable
        public init(accountId: String? = nil, administratorId: String? = nil, datasourcePackageIngestStates: [DatasourcePackage: DatasourcePackageIngestState]? = nil, disabledReason: MemberDisabledReason? = nil, emailAddress: String? = nil, graphArn: String? = nil, invitationType: InvitationType? = nil, invitedTime: Date? = nil, status: MemberStatus? = nil, updatedTime: Date? = nil, volumeUsageByDatasourcePackage: [DatasourcePackage: DatasourcePackageUsageInfo]? = nil) {
            self.accountId = accountId
            self.administratorId = administratorId
            self.datasourcePackageIngestStates = datasourcePackageIngestStates
            self.disabledReason = disabledReason
            self.emailAddress = emailAddress
            self.graphArn = graphArn
            self.invitationType = invitationType
            self.invitedTime = invitedTime
            self.masterId = nil
            self.percentOfGraphUtilization = nil
            self.percentOfGraphUtilizationUpdatedTime = nil
            self.status = status
            self.updatedTime = updatedTime
            self.volumeUsageByDatasourcePackage = volumeUsageByDatasourcePackage
            self.volumeUsageInBytes = nil
            self.volumeUsageUpdatedTime = nil
        }

        @available(*, deprecated, message: "Members masterId, percentOfGraphUtilization, percentOfGraphUtilizationUpdatedTime, volumeUsageInBytes, volumeUsageUpdatedTime have been deprecated")
        @inlinable
        public init(accountId: String? = nil, administratorId: String? = nil, datasourcePackageIngestStates: [DatasourcePackage: DatasourcePackageIngestState]? = nil, disabledReason: MemberDisabledReason? = nil, emailAddress: String? = nil, graphArn: String? = nil, invitationType: InvitationType? = nil, invitedTime: Date? = nil, masterId: String? = nil, percentOfGraphUtilization: Double? = nil, percentOfGraphUtilizationUpdatedTime: Date? = nil, status: MemberStatus? = nil, updatedTime: Date? = nil, volumeUsageByDatasourcePackage: [DatasourcePackage: DatasourcePackageUsageInfo]? = nil, volumeUsageInBytes: Int64? = nil, volumeUsageUpdatedTime: Date? = nil) {
            self.accountId = accountId
            self.administratorId = administratorId
            self.datasourcePackageIngestStates = datasourcePackageIngestStates
            self.disabledReason = disabledReason
            self.emailAddress = emailAddress
            self.graphArn = graphArn
            self.invitationType = invitationType
            self.invitedTime = invitedTime
            self.masterId = masterId
            self.percentOfGraphUtilization = percentOfGraphUtilization
            self.percentOfGraphUtilizationUpdatedTime = percentOfGraphUtilizationUpdatedTime
            self.status = status
            self.updatedTime = updatedTime
            self.volumeUsageByDatasourcePackage = volumeUsageByDatasourcePackage
            self.volumeUsageInBytes = volumeUsageInBytes
            self.volumeUsageUpdatedTime = volumeUsageUpdatedTime
        }

        private enum CodingKeys: String, CodingKey {
            case accountId = "AccountId"
            case administratorId = "AdministratorId"
            case datasourcePackageIngestStates = "DatasourcePackageIngestStates"
            case disabledReason = "DisabledReason"
            case emailAddress = "EmailAddress"
            case graphArn = "GraphArn"
            case invitationType = "InvitationType"
            case invitedTime = "InvitedTime"
            case masterId = "MasterId"
            case percentOfGraphUtilization = "PercentOfGraphUtilization"
            case percentOfGraphUtilizationUpdatedTime = "PercentOfGraphUtilizationUpdatedTime"
            case status = "Status"
            case updatedTime = "UpdatedTime"
            case volumeUsageByDatasourcePackage = "VolumeUsageByDatasourcePackage"
            case volumeUsageInBytes = "VolumeUsageInBytes"
            case volumeUsageUpdatedTime = "VolumeUsageUpdatedTime"
        }
    }

    public struct MembershipDatasources: AWSDecodableShape {
        /// The account identifier of the Amazon Web Services account.
        public let accountId: String?
        /// Details on when a data source package was added to a behavior graph.
        public let datasourcePackageIngestHistory: [DatasourcePackage: [DatasourcePackageIngestState: TimestampForCollection]]?
        /// The ARN of the organization behavior graph.
        public let graphArn: String?

        @inlinable
        public init(accountId: String? = nil, datasourcePackageIngestHistory: [DatasourcePackage: [DatasourcePackageIngestState: TimestampForCollection]]? = nil, graphArn: String? = nil) {
            self.accountId = accountId
            self.datasourcePackageIngestHistory = datasourcePackageIngestHistory
            self.graphArn = graphArn
        }

        private enum CodingKeys: String, CodingKey {
            case accountId = "AccountId"
            case datasourcePackageIngestHistory = "DatasourcePackageIngestHistory"
            case graphArn = "GraphArn"
        }
    }

    public struct NewAsoDetail: AWSDecodableShape {
        /// Details about the new Autonomous System Organization (ASO).
        public let aso: String?
        /// Checks if the Autonomous System Organization (ASO) is new for the entire account.
        public let isNewForEntireAccount: Bool?

        @inlinable
        public init(aso: String? = nil, isNewForEntireAccount: Bool? = nil) {
            self.aso = aso
            self.isNewForEntireAccount = isNewForEntireAccount
        }

        private enum CodingKeys: String, CodingKey {
            case aso = "Aso"
            case isNewForEntireAccount = "IsNewForEntireAccount"
        }
    }

    public struct NewGeolocationDetail: AWSDecodableShape {
        /// IP address using which the resource was accessed.
        public let ipAddress: String?
        /// Checks if the geolocation is new for the entire account.
        public let isNewForEntireAccount: Bool?
        /// Location where the resource was accessed.
        public let location: String?

        @inlinable
        public init(ipAddress: String? = nil, isNewForEntireAccount: Bool? = nil, location: String? = nil) {
            self.ipAddress = ipAddress
            self.isNewForEntireAccount = isNewForEntireAccount
            self.location = location
        }

        private enum CodingKeys: String, CodingKey {
            case ipAddress = "IpAddress"
            case isNewForEntireAccount = "IsNewForEntireAccount"
            case location = "Location"
        }
    }

    public struct NewUserAgentDetail: AWSDecodableShape {
        /// Checks if the user agent is new for the entire account.
        public let isNewForEntireAccount: Bool?
        /// New user agent which accessed the resource.
        public let userAgent: String?

        @inlinable
        public init(isNewForEntireAccount: Bool? = nil, userAgent: String? = nil) {
            self.isNewForEntireAccount = isNewForEntireAccount
            self.userAgent = userAgent
        }

        private enum CodingKeys: String, CodingKey {
            case isNewForEntireAccount = "IsNewForEntireAccount"
            case userAgent = "UserAgent"
        }
    }

    public struct RejectInvitationRequest: AWSEncodableShape {
        /// The ARN of the behavior graph to reject the invitation to. The member account's current member status in the behavior graph must be INVITED.
        public let graphArn: String

        @inlinable
        public init(graphArn: String) {
            self.graphArn = graphArn
        }

        public func validate(name: String) throws {
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
        }

        private enum CodingKeys: String, CodingKey {
            case graphArn = "GraphArn"
        }
    }

    public struct RelatedFindingDetail: AWSDecodableShape {
        /// The Amazon Resource Name (ARN) of the related finding.
        public let arn: String?
        /// The IP address of the finding.
        public let ipAddress: String?
        /// The type of finding.
        public let type: String?

        @inlinable
        public init(arn: String? = nil, ipAddress: String? = nil, type: String? = nil) {
            self.arn = arn
            self.ipAddress = ipAddress
            self.type = type
        }

        private enum CodingKeys: String, CodingKey {
            case arn = "Arn"
            case ipAddress = "IpAddress"
            case type = "Type"
        }
    }

    public struct RelatedFindingGroupDetail: AWSDecodableShape {
        /// The unique identifier for the finding group.
        public let id: String?

        @inlinable
        public init(id: String? = nil) {
            self.id = id
        }

        private enum CodingKeys: String, CodingKey {
            case id = "Id"
        }
    }

    public struct ServiceQuotaExceededException: AWSErrorShape {
        public let message: String?
        /// The type of resource that has exceeded the service quota.
        public let resources: [String]?

        @inlinable
        public init(message: String? = nil, resources: [String]? = nil) {
            self.message = message
            self.resources = resources
        }

        private enum CodingKeys: String, CodingKey {
            case message = "Message"
            case resources = "Resources"
        }
    }

    public struct SortCriteria: AWSEncodableShape {
        /// Represents the Field attribute to sort investigations.
        public let field: Field?
        /// The order by which the sorted findings are displayed.
        public let sortOrder: SortOrder?

        @inlinable
        public init(field: Field? = nil, sortOrder: SortOrder? = nil) {
            self.field = field
            self.sortOrder = sortOrder
        }

        private enum CodingKeys: String, CodingKey {
            case field = "Field"
            case sortOrder = "SortOrder"
        }
    }

    public struct StartInvestigationRequest: AWSEncodableShape {
        /// The unique Amazon Resource Name (ARN) of the IAM user and IAM role.
        public let entityArn: String
        /// The Amazon Resource Name (ARN) of the behavior graph.
        public let graphArn: String
        /// The data and time when the investigation ended. The value is an UTC ISO8601 formatted string. For example, 2021-08-18T16:35:56.284Z.
        @CustomCoding<ISO8601DateCoder>
        public var scopeEndTime: Date
        /// The data and time when the investigation began. The value is an UTC ISO8601 formatted string. For example, 2021-08-18T16:35:56.284Z.
        @CustomCoding<ISO8601DateCoder>
        public var scopeStartTime: Date

        @inlinable
        public init(entityArn: String, graphArn: String, scopeEndTime: Date, scopeStartTime: Date) {
            self.entityArn = entityArn
            self.graphArn = graphArn
            self.scopeEndTime = scopeEndTime
            self.scopeStartTime = scopeStartTime
        }

        public func validate(name: String) throws {
            try self.validate(self.entityArn, name: "entityArn", parent: name, pattern: "^arn:")
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
        }

        private enum CodingKeys: String, CodingKey {
            case entityArn = "EntityArn"
            case graphArn = "GraphArn"
            case scopeEndTime = "ScopeEndTime"
            case scopeStartTime = "ScopeStartTime"
        }
    }

    public struct StartInvestigationResponse: AWSDecodableShape {
        /// The investigation ID of the investigation report.
        public let investigationId: String?

        @inlinable
        public init(investigationId: String? = nil) {
            self.investigationId = investigationId
        }

        private enum CodingKeys: String, CodingKey {
            case investigationId = "InvestigationId"
        }
    }

    public struct StartMonitoringMemberRequest: AWSEncodableShape {
        /// The account ID of the member account to try to enable. The account must be an invited member account with a status of ACCEPTED_BUT_DISABLED.
        public let accountId: String
        /// The ARN of the behavior graph.
        public let graphArn: String

        @inlinable
        public init(accountId: String, graphArn: String) {
            self.accountId = accountId
            self.graphArn = graphArn
        }

        public func validate(name: String) throws {
            try self.validate(self.accountId, name: "accountId", parent: name, max: 12)
            try self.validate(self.accountId, name: "accountId", parent: name, min: 12)
            try self.validate(self.accountId, name: "accountId", parent: name, pattern: "^[0-9]+$")
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
        }

        private enum CodingKeys: String, CodingKey {
            case accountId = "AccountId"
            case graphArn = "GraphArn"
        }
    }

    public struct StringFilter: AWSEncodableShape {
        /// The string filter value.
        public let value: String

        @inlinable
        public init(value: String) {
            self.value = value
        }

        public func validate(name: String) throws {
            try self.validate(self.value, name: "value", parent: name, max: 500)
            try self.validate(self.value, name: "value", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case value = "Value"
        }
    }

    public struct TTPsObservedDetail: AWSDecodableShape {
        /// The total number of failed API requests.
        public let apiFailureCount: Int64?
        /// The name of the API where the tactics, techniques, and procedure (TTP) was observed.
        public let apiName: String?
        /// The total number of successful API requests.
        public let apiSuccessCount: Int64?
        /// The IP address where the tactics, techniques, and procedure (TTP) was observed.
        public let ipAddress: String?
        /// The procedure used, identified by the investigation.
        public let procedure: String?
        /// The tactic used, identified by the investigation.
        public let tactic: String?
        /// The technique used, identified by the investigation.
        public let technique: String?

        @inlinable
        public init(apiFailureCount: Int64? = nil, apiName: String? = nil, apiSuccessCount: Int64? = nil, ipAddress: String? = nil, procedure: String? = nil, tactic: String? = nil, technique: String? = nil) {
            self.apiFailureCount = apiFailureCount
            self.apiName = apiName
            self.apiSuccessCount = apiSuccessCount
            self.ipAddress = ipAddress
            self.procedure = procedure
            self.tactic = tactic
            self.technique = technique
        }

        private enum CodingKeys: String, CodingKey {
            case apiFailureCount = "APIFailureCount"
            case apiName = "APIName"
            case apiSuccessCount = "APISuccessCount"
            case ipAddress = "IpAddress"
            case procedure = "Procedure"
            case tactic = "Tactic"
            case technique = "Technique"
        }
    }

    public struct TagResourceRequest: AWSEncodableShape {
        /// The ARN of the behavior graph to assign the tags to.
        public let resourceArn: String
        /// The tags to assign to the behavior graph. You can add up to 50 tags. For each tag, you provide the tag key and the tag value. Each tag key can contain up to 128 characters. Each tag value can contain up to 256 characters.
        public let tags: [String: String]

        @inlinable
        public init(resourceArn: String, tags: [String: String]) {
            self.resourceArn = resourceArn
            self.tags = tags
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            var container = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "ResourceArn")
            try container.encode(self.tags, forKey: .tags)
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
            try self.tags.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.key, name: "tags.key", parent: name, pattern: "^(?!aws:)[a-zA-Z+-=._:/]+$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 50)
            try self.validate(self.tags, name: "tags", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "Tags"
        }
    }

    public struct TagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct TimestampForCollection: AWSDecodableShape {
        /// The data and time when data collection began for a source package. The value is an ISO8601 formatted string. For example, 2021-08-18T16:35:56.284Z.
        @OptionalCustomCoding<ISO8601DateCoder>
        public var timestamp: Date?

        @inlinable
        public init(timestamp: Date? = nil) {
            self.timestamp = timestamp
        }

        private enum CodingKeys: String, CodingKey {
            case timestamp = "Timestamp"
        }
    }

    public struct UnprocessedAccount: AWSDecodableShape {
        /// The Amazon Web Services account identifier of the member account that was not processed.
        public let accountId: String?
        /// The reason that the member account request could not be processed.
        public let reason: String?

        @inlinable
        public init(accountId: String? = nil, reason: String? = nil) {
            self.accountId = accountId
            self.reason = reason
        }

        private enum CodingKeys: String, CodingKey {
            case accountId = "AccountId"
            case reason = "Reason"
        }
    }

    public struct UnprocessedGraph: AWSDecodableShape {
        /// The ARN of the organization behavior graph.
        public let graphArn: String?
        /// The reason data source package information could not be processed for a behavior graph.
        public let reason: String?

        @inlinable
        public init(graphArn: String? = nil, reason: String? = nil) {
            self.graphArn = graphArn
            self.reason = reason
        }

        private enum CodingKeys: String, CodingKey {
            case graphArn = "GraphArn"
            case reason = "Reason"
        }
    }

    public struct UntagResourceRequest: AWSEncodableShape {
        /// The ARN of the behavior graph to remove the tags from.
        public let resourceArn: String
        /// The tag keys of the tags to remove from the behavior graph. You can remove up to 50 tags at a time.
        public let tagKeys: [String]

        @inlinable
        public init(resourceArn: String, tagKeys: [String]) {
            self.resourceArn = resourceArn
            self.tagKeys = tagKeys
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "ResourceArn")
            request.encodeQuery(self.tagKeys, key: "tagKeys")
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
            try self.tagKeys.forEach {
                try validate($0, name: "tagKeys[]", parent: name, max: 128)
                try validate($0, name: "tagKeys[]", parent: name, min: 1)
                try validate($0, name: "tagKeys[]", parent: name, pattern: "^(?!aws:)[a-zA-Z+-=._:/]+$")
            }
            try self.validate(self.tagKeys, name: "tagKeys", parent: name, max: 50)
            try self.validate(self.tagKeys, name: "tagKeys", parent: name, min: 1)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct UntagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct UpdateDatasourcePackagesRequest: AWSEncodableShape {
        /// The data source package to start for the behavior graph.
        public let datasourcePackages: [DatasourcePackage]
        /// The ARN of the behavior graph.
        public let graphArn: String

        @inlinable
        public init(datasourcePackages: [DatasourcePackage], graphArn: String) {
            self.datasourcePackages = datasourcePackages
            self.graphArn = graphArn
        }

        public func validate(name: String) throws {
            try self.validate(self.datasourcePackages, name: "datasourcePackages", parent: name, max: 25)
            try self.validate(self.datasourcePackages, name: "datasourcePackages", parent: name, min: 1)
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
        }

        private enum CodingKeys: String, CodingKey {
            case datasourcePackages = "DatasourcePackages"
            case graphArn = "GraphArn"
        }
    }

    public struct UpdateInvestigationStateRequest: AWSEncodableShape {
        /// The Amazon Resource Name (ARN) of the behavior graph.
        public let graphArn: String
        /// The investigation ID of the investigation report.
        public let investigationId: String
        /// The current state of the investigation. An archived investigation indicates you have completed reviewing the investigation.
        public let state: State

        @inlinable
        public init(graphArn: String, investigationId: String, state: State) {
            self.graphArn = graphArn
            self.investigationId = investigationId
            self.state = state
        }

        public func validate(name: String) throws {
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
            try self.validate(self.investigationId, name: "investigationId", parent: name, max: 21)
            try self.validate(self.investigationId, name: "investigationId", parent: name, min: 21)
            try self.validate(self.investigationId, name: "investigationId", parent: name, pattern: "^[0-9]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case graphArn = "GraphArn"
            case investigationId = "InvestigationId"
            case state = "State"
        }
    }

    public struct UpdateOrganizationConfigurationRequest: AWSEncodableShape {
        /// Indicates whether to automatically enable new organization accounts as member accounts in the organization behavior graph.
        public let autoEnable: Bool?
        /// The ARN of the organization behavior graph.
        public let graphArn: String

        @inlinable
        public init(autoEnable: Bool? = nil, graphArn: String) {
            self.autoEnable = autoEnable
            self.graphArn = graphArn
        }

        public func validate(name: String) throws {
            try self.validate(self.graphArn, name: "graphArn", parent: name, pattern: "^arn:aws[-\\w]{0,10}?:detective:[-\\w]{2,20}?:\\d{12}?:graph:[abcdef\\d]{32}?$")
        }

        private enum CodingKeys: String, CodingKey {
            case autoEnable = "AutoEnable"
            case graphArn = "GraphArn"
        }
    }

    public struct ValidationException: AWSErrorShape {
        /// The error code associated with the validation failure.
        public let errorCode: ErrorCode?
        ///  An explanation of why validation failed.
        public let errorCodeReason: String?
        public let message: String?

        @inlinable
        public init(errorCode: ErrorCode? = nil, errorCodeReason: String? = nil, message: String? = nil) {
            self.errorCode = errorCode
            self.errorCodeReason = errorCodeReason
            self.message = message
        }

        private enum CodingKeys: String, CodingKey {
            case errorCode = "ErrorCode"
            case errorCodeReason = "ErrorCodeReason"
            case message = "Message"
        }
    }
}

// MARK: - Errors

/// Error enum for Detective
public struct DetectiveErrorType: AWSErrorType {
    enum Code: String {
        case accessDeniedException = "AccessDeniedException"
        case conflictException = "ConflictException"
        case internalServerException = "InternalServerException"
        case resourceNotFoundException = "ResourceNotFoundException"
        case serviceQuotaExceededException = "ServiceQuotaExceededException"
        case tooManyRequestsException = "TooManyRequestsException"
        case validationException = "ValidationException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize Detective
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// The request issuer does not have permission to access this resource or perform this operation.
    public static var accessDeniedException: Self { .init(.accessDeniedException) }
    /// The request attempted an invalid action.
    public static var conflictException: Self { .init(.conflictException) }
    /// The request was valid but failed because of a problem with the service.
    public static var internalServerException: Self { .init(.internalServerException) }
    /// The request refers to a nonexistent resource.
    public static var resourceNotFoundException: Self { .init(.resourceNotFoundException) }
    /// This request cannot be completed for one of the following reasons.   This request cannot be completed if it would cause the number of member accounts in the behavior graph to exceed the maximum allowed. A behavior graph cannot have more than 1,200 member accounts.   This request cannot be completed if the current volume ingested is above the limit of 10 TB per day. Detective will not allow you to add additional member accounts.
    public static var serviceQuotaExceededException: Self { .init(.serviceQuotaExceededException) }
    /// The request cannot be completed because too many other requests are occurring at the same time.
    public static var tooManyRequestsException: Self { .init(.tooManyRequestsException) }
    /// The request parameters are invalid.
    public static var validationException: Self { .init(.validationException) }
}

extension DetectiveErrorType: AWSServiceErrorType {
    public static let errorCodeMap: [String: AWSErrorShape.Type] = [
        "AccessDeniedException": Detective.AccessDeniedException.self,
        "ServiceQuotaExceededException": Detective.ServiceQuotaExceededException.self,
        "ValidationException": Detective.ValidationException.self
    ]
}

extension DetectiveErrorType: Equatable {
    public static func == (lhs: DetectiveErrorType, rhs: DetectiveErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension DetectiveErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
